package com.db.server;

import com.db.protocol.Command;
import com.db.protocol.Request;
import com.db.server.task.Task;
import com.db.server.task.TaskQueue;
import com.db.server.task.TaskSendMessage;

import java.io.*;
import java.net.Socket;


/**
 * RequestReceiver is created when new client was added.
 * RequestReceiver gets requests from client and processes them.
 * RequestReceiver creates new thread for sending messages for this client;
 */
public class RequestReceiver extends Thread {
    private boolean isCorrectName = false;
    private String name;
    private Socket socket;
    private TaskQueue taskQueue;
    private ServerSession serverSession;

    /**
     * ctor
     * @param socket Socket associated with client.
     * @param serverSession Server session with all clients.
     */
    RequestReceiver(Socket socket, ServerSession serverSession, TaskQueue taskQueue) {
        this.socket = socket;
        this.serverSession = serverSession;
        this.taskQueue = taskQueue;
    }

    private void parseCommand(Command command, String[] args) {
        switch (command) {
            case snd:
                serverSession.sendMessage(this, args[0]);
                break;
            case chid:
                if (serverSession.login(this, args[0], args[1])) {
                    name = args[0];
                    isCorrectName = true;
                }
                break;
            case hist:
                serverSession.getHistory(this);
                break;
            case histr:
                serverSession.getRoomHistory(this);
                break;
            case histp:
                serverSession.getPrivateHistory(this);
                break;
            case chroom:
                serverSession.setRoomName(this, args[0]);
                break;
            case sndp:
                serverSession.sendPrivateMessage(this, args[0], args[1]);
                break;
            case gtrooms:
                serverSession.getRoomList(this);
                break;
            case disconnect:
                return;
            default:
                taskQueue.add(new TaskSendMessage("incorrect command"));
                break;
        }
    }

    public void run() {
        ResponseSender sender = null;
        try (ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
                ObjectInputStream in = new ObjectInputStream(socket.getInputStream())) {
            sender = new ResponseSender(taskQueue, out);
            sender.start();
            Request request;
            while (true) {
                try {
                    request = (Request) in.readObject();
                } catch (ClassNotFoundException | ClassCastException e) {
                    continue;
                }
                Command command = request.getCommand();
                String[] params = request.getArgument();
                if (command == Command.disconnect) {
                    return;
                }
                if (isCorrectName == false && command != Command.chid) {
                    taskQueue.add(new TaskSendMessage("please, enter your name. Command: chid <name> <pass>"));
                    continue;
                }
                parseCommand(command, params);
            }
        } catch (IOException e) {
        } finally {
            if (sender != null) sender.interrupt();
            System.out.println("client " + name + " was disconnected.");
            serverSession.removeClient(this);
        }
    }

    public void addTask(Task task) {
        taskQueue.add(task);
    }

    public void addServerMessage(String message) {
        taskQueue.add(new TaskSendMessage(message));
    }


    public String getClientName() {
        return name;
    }

}
